package com.itheima.listener;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.api.ChannelAwareMessageListener;
import org.springframework.stereotype.Component;

/**
 * Consumer ACK机制：
 * 1. 设置手动签收。acknowledge="manual"
 * 2. 让监听器类实现ChannelAwareMessageListener接口
 * 3. 如果消息成功处理，则调用channel的 basicAck()签收
 * 4. 如果消息处理失败，则调用channel的basicNack()拒绝签收，broker重新发送给consumer
 */

@Component
public class AckListener implements ChannelAwareMessageListener {

    @Override
    public void onMessage(Message message, Channel channel) throws Exception {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        try {
            //1.接收转换消息
            System.out.println(new String(message.getBody()));

            //2. 处理业务逻辑
            System.out.println("处理业务逻辑...");
            int i = 3 / 0;//出现错误
            //3. 手动签收
            /*
             * deliveryTag:该消息的index
             * multiple：是否批量. true：将一次性ack所有小于deliveryTag的消息。
             */
            channel.basicAck(deliveryTag, true);
        } catch (Exception e) {
            //e.printStackTrace();

            //4.拒绝签收
            /*
             * deliveryTag:该消息的index。
             * multiple：是否批量. true：将一次性拒绝所有小于deliveryTag的消息。
             * requeue：被拒绝的是否重新入队列。
             *          true:若重回队列 会一直循环 接收消息->手动拒绝->重回队列->接收消息->
             *          false:不重回队列 不会循环接收消息，但是当处理好异常之后，就会发现消息丢失了
             */
            channel.basicNack(deliveryTag, true, true);
                        /*
            一次只能拒绝一条消息
             * deliveryTag:该消息的index。
             * requeue：被拒绝的是否重新入队列。
             */
            //channel.basicReject(deliveryTag,true);
        }
    }
}
